package mybatisflex.codegen.factory;

import cn.hutool.core.date.DateUtil;
import com.diaohw.platform.framework.db.flex.generator.GeneratorFactoryBuild;
import com.diaohw.platform.framework.db.flex.obj.model.BaseModel;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.codegen.Generator;
import com.mybatisflex.codegen.config.ColumnConfig;
import com.mybatisflex.codegen.config.EntityConfig;
import com.mybatisflex.codegen.config.GlobalConfig;
import com.mybatisflex.codegen.config.TableDefConfig;
import com.mybatisflex.codegen.constant.GenTypeConst;
import com.mybatisflex.codegen.dialect.IDialect;
import com.mybatisflex.codegen.dialect.JdbcTypeMapping;
import com.mybatisflex.codegen.generator.GeneratorFactory;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.keygen.KeyGenerators;
import com.mybatisflex.core.service.IService;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.zaxxer.hikari.HikariDataSource;
import lombok.SneakyThrows;

import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;

public class GlobalGeneratorFactory {


    public static HikariDataSource getDatasource(String url, String username, String password) {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    public static void generate(GeneratorFactoryBuild data) {
        GlobalConfig globalConfig = createGlobalConfig(data);
        Generator generator = new Generator(
                getDatasource(data.getUrl(), data.getUsername(), data.getPassword()),
                globalConfig,
                IDialect.MYSQL);
        GeneratorFactory.registerGenerator(GenTypeConst.ENTITY, data.getEntityGenerator());
        GeneratorFactory.registerGenerator(GenTypeConst.MAPPER, data.getMapperGenerator());
        GeneratorFactory.registerGenerator(GenTypeConst.SERVICE, data.getServiceGenerator());
        GeneratorFactory.registerGenerator(GenTypeConst.SERVICE_IMPL, data.getImplGenerator());
        GeneratorFactory.registerGenerator(GenTypeConst.CONTROLLER, data.getControllerGenerator());
        GeneratorFactory.registerGenerator("dto", new CustomerEntityGenerator("DTO", "obj.dto"));
        GeneratorFactory.registerGenerator("query", new CustomerEntityGenerator("Query", "obj.query"));
        GeneratorFactory.registerGenerator("mapstruct", new MapstructGenerator("Mapstruct", "obj.mapstruct"));

        JdbcTypeMapping.registerMapping(LocalDateTime.class, Date.class);
        JdbcTypeMapping.registerMapping(Double.class, BigDecimal.class);

        generator.generate();
    }


    @SneakyThrows
    public static GlobalConfig createGlobalConfig(GeneratorFactoryBuild data) {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setBasePackage(data.getBaseClass().getPackageName());
        if (data.getTables() != null) {
            globalConfig.setGenerateTable(data.getTables());
        }
        File file = new File(new File(Objects.requireNonNull(data.getBaseClass().getClassLoader().getResource("")).toURI()).getParentFile().getParentFile(), "src/main/java");
        globalConfig.setSourceDir(file.getAbsolutePath());
        globalConfig.setBasePackage(data.getBaseClass().getPackage().getName());

        //设置生成 entity 并启用 Lombok
        globalConfig.setEntityWithLombok(true);
        globalConfig.setEntityGenerateEnable(data.isEnableEntity());
        globalConfig.setMapperGenerateEnable(data.isEnableMapper());
        globalConfig.setServiceGenerateEnable(data.isEnableService());
        globalConfig.setServiceImplGenerateEnable(data.isEnableService());
        globalConfig.setControllerGenerateEnable(data.isEnableController());
        globalConfig.setTableDefGenerateEnable(data.isEnableTableDef());
        globalConfig.setMapperXmlGenerateEnable(data.isEnableMapper());

        globalConfig.getPackageConfig()
                .setEntityPackage(globalConfig.getBasePackage() + ".obj.entity")
                .setServiceImplPackage(globalConfig.getBasePackage() + ".service.impl")
                .setMapperPackage(globalConfig.getBasePackage() + ".mapper")
                .setControllerPackage(globalConfig.getBasePackage() + ".controller")
                .setTableDefPackage(globalConfig.getBasePackage() + ".obj.tables")
               ;

        // 注释配置
        globalConfig.getJavadocConfig()
                .setAuthor(data.getAuthor())

                .setSince(DateUtil.now());

        // 策略配置
        ColumnConfig idConfig = new ColumnConfig();
        idConfig.setColumnName("id");
        idConfig.setKeyType(KeyType.Generator);
        idConfig.setKeyValue(KeyGenerators.snowFlakeId);
        idConfig.setPrimaryKey(true);

        globalConfig.getStrategyConfig()
                .setColumnConfig(idConfig);
        // Entity 生成配置
        globalConfig.enableEntity()
                .setSuperClass(BaseModel.class)
                .setClassSuffix("DO")
                .setOverwriteEnable(true)
                .setSwaggerVersion(EntityConfig.SwaggerVersion.DOC)
//                    .setWithActiveRecord(true)
                .setJdkVersion(17)
                .setAlwaysGenColumnAnnotation(true)
                .setWithLombok(true);
        globalConfig.enableTableDef()
                .setOverwriteEnable(true)
                .setPropertiesNameStyle(TableDefConfig.NameStyle.UPPER_CASE)
                .setClassSuffix("Def");
        globalConfig.enableService()
                .setClassSuffix("Service")
                .setOverwriteEnable(true)
                .setSuperClass(IService.class);

        globalConfig.enableServiceImpl()
                .setClassSuffix("Impl")
                .setOverwriteEnable(true)
                .setSuperClass(ServiceImpl.class);

        globalConfig.enableController()
                .setOverwriteEnable(true)
                .setClassSuffix("Controller")
                .setRestStyle(true);
        // Mapper 生成配置
        globalConfig.enableMapper()
                .setClassSuffix("Mapper")
                .setOverwriteEnable(true)
                .setSuperClass(BaseMapper.class)
                .setMapperAnnotation(true);
        globalConfig.enableMapperXml()
                .setOverwriteEnable(true)
                .setFileSuffix("Mapper");

        return globalConfig;
    }


}
